"""
===============================
@author     : yaoruiqi

@Time       : 2022/6/15 11:28

@version    : V

@introduce  :

@change     : 
===============================
"""
import json
import random
import re
import time

from faker.factory import Factory
import unicodedata
from binascii import a2b_hex
from hashlib import md5
from random import randint
from uuid import uuid4

import requests
from Crypto.Cipher import AES

from loguru import logger
import sys
modules = sys.modules[__name__]

from ftlangdetect import detect


class MyRetry:

    def __init__(self, times=1, sleep_time=0, custom_return=(False, False), return_msg=False, show_params=False, show_process=True):
        """
        重试模块
        :param times: 重试次数
        :param sleep_time: 重试间隔时间
        :param custom_return: 自定义返回内容 当custom_return[0]为True时，返回custom_return[1]
        :param return_msg: 重试失败后打印的字符串
        :param show_params: 重试失败后是否打印传入的参数
        :param show_process: 是否打印重试过程
        """
        self.times = times
        self.sleep_time = sleep_time
        self.custom_return = custom_return
        self.return_msg = return_msg
        self.show_params = show_params
        self.show_process = show_process

    def __call__(self, fun):
        retry_time = self.times
        sleep_time = self.sleep_time
        custom_return = self.custom_return
        return_msg = self.return_msg
        show_params = self.show_params
        show_process = self.show_process

        def retry_handle(*args, **kwargs):
            msg = f'函数: {fun.__name__} 重试{retry_time}次后发生异常\n'
            for t in range(retry_time):
                try:
                    fun_res = fun(*args, **kwargs)
                except Exception as e:
                    if t == retry_time - 1:
                        # 重试失败
                        if return_msg:
                            msg += f'MESSAGE: {return_msg}\n'
                        if show_params:
                            msg += f'PARAMS: {args}  {kwargs}\n'
                        # logger.exception(msg)
                        if custom_return[0]:
                            return custom_return[1]
                        else:
                            raise AssertionError(e)
                    else:
                        if show_process:
                            logger.warning(f'函数: {fun.__name__} 发生异常，第{t + 1}次重试，失败原因：{e}')
                        if sleep_time:
                            time.sleep(sleep_time)

                else:
                    return fun_res

        return retry_handle


class Proxy:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if Proxy._instance is None:
            Proxy._instance = super().__new__(cls)
        return Proxy._instance

    @staticmethod
    def decrypt(text):
        key = "%qq123456.".ljust(16, '\0').encode('utf-8')
        iv_b = ("%qq123456.".ljust(16, '\0')).encode('utf-8')
        cryptos = AES.new(key, AES.MODE_CBC, iv_b)
        plain_text = cryptos.decrypt(a2b_hex(text))
        return bytes.decode(plain_text).rstrip('\0')

    @MyRetry(times=3, custom_return=(True, {}))
    def get_proxy(self):
        # url = 'http://192.168.100.42:7010/get/?num=1&token=%qq123456..&qname=robot'
        url = "http://192.168.44.9/get/?token=%qq123456..&qname=spider1&num="
        res = requests.get(url, timeout=5).json()
        proxy_list = res.get('proxy_list')
        assert res['code'] == '1' and res['message'] == '获取成功' and proxy_list, '代理请求失败'
        info = json.loads(res.get('proxy_list')[0])
        pw = self.decrypt(info["password"])
        if info.get('type') == 1:
            return {
                "http": f"http://{info['user']}:{pw}@{info['proxy_ip']}",
                "https": f"http://{info['user']}:{pw}@{info['proxy_ip']}"
            }
        else:
            return {"http": f"http://{info['proxy_ip']}", "https": f"http://{info['proxy_ip']}"}




class XiaoNiu:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if XiaoNiu._instance is None:
            XiaoNiu._instance = super().__new__(cls)
        return XiaoNiu._instance

    @staticmethod
    @MyRetry(times=3, custom_return=(True, False))
    def translate(from_lang, to_lang, text):
        api_key = 'f1a07f8d3cdab8ed7e5176038e3c122f'
        url_text = f'http://111.161.65.69:8063/niutrans/textTranslation?apikey={api_key}'
        data = {'from': from_lang, 'to': to_lang, 'src_text': text}
        header = {"Content-Type": "application/json", "Connection": "close"}
        respon = requests.post(url_text, data=json.dumps(data), headers=header, timeout=60).json()
        assert respon['code'] == 200, '小牛翻译请求失败'
        result = ''.join([i['data'] for i in respon['data'][0]['sentences']])
        if result[-1] == ' ':
            result = result[0:-1]
        return result

class MinorityLanguage:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if MinorityLanguage._instance is None:
            MinorityLanguage._instance = super().__new__(cls)
        return MinorityLanguage._instance

    @staticmethod
    @MyRetry(times=3, custom_return=(True, False))
    def translate(from_lang, to_lang, text):
        url_text = f'http://192.168.44.184:9090/api/fanyi'
        data = {'from_lang':from_lang,'to_lang': to_lang, 'text': text}
        header = {"Content-Type": "application/json", "Connection": "close", 'key':'kang_translate'}
        respon = requests.post(url_text, json=data, headers=header, timeout=60)
        assert respon.status_code == 200, '小语种翻译请求失败'
        final_data = respon.json()
        assert final_data['code'] == 200, final_data['data']
        result = respon.json()["data"]
        assert result, f'返回结果错误：{result}'
        return result


class TranslateManager:
    _instance=None

    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if TranslateManager._instance is None:
            TranslateManager._instance = super().__new__(cls)
        return TranslateManager._instance


    # 文本字符拆分
    def textsplit(self, translate_text, splitnumber: int = 3000):
        split_list = []
        if len(translate_text) > splitnumber:
            logger.info(f"检测字符数量为：{len(translate_text)}，大于 {splitnumber}，需切分")
            while True:
                new_text = translate_text[:splitnumber]
                if len(translate_text) > splitnumber:
                    if '.' not in new_text:
                        # 针对日文
                        if '．' not in new_text:
                            if '。' not in new_text:
                                logger.warning(f"检测 2000 字符内不包含切割符 无法处理\n数据为:{new_text}")
                                # return '无法切割字符'
                                split_list.append(translate_text)
                                return split_list

                            new_index = new_text.rfind('。')
                        else:
                            new_index = new_text.rfind('．')
                    else:
                        new_index = new_text.rfind('.')
                    cont = translate_text[:int(new_index) + 1]
                    split_list.append(cont.strip())
                    translate_text = translate_text.replace(cont, '')
                else:
                    split_list.append(new_text.strip())
                    break
            return split_list
        else:
            # logger.info(f"检测字符数量为：{len(translate_text)}，小于 {splitnumber}")
            split_list.append(translate_text)
            return split_list

    def get_language(self,text):
        return detect(text=text, low_memory=False)['lang']

    def manager(self, text,from_lang='AUTO',to_lang=None):
        try:
            assert to_lang, f'翻译失败，需要提供要翻译成什么语种'
            if re.search(r'^\W*$|^\d$|^\w{1}$|^\s*$|^½$', text):
                return text
            # 识别语种
            if from_lang == 'AUTO':
                from_lang = detect(text=text, low_memory=False)['lang']
                logger.debug(f'检测语种为：{from_lang}')
            text = unicodedata.normalize('NFKD', text)

            text_list = self.textsplit(text)
            translate_text = ''
            for one_text in text_list:
                if from_lang == 'en':
                    result = XiaoNiu.translate(from_lang=from_lang, to_lang=to_lang, text=one_text)
                elif from_lang == "zh":
                    result = XiaoNiu.translate(from_lang=from_lang, to_lang=to_lang, text=one_text)
                else:
                    result = MinorityLanguage.translate(from_lang=from_lang, to_lang=to_lang, text=one_text)
                    if result:
                        logger.info('小语种翻译成功')
                assert result, f'单次翻译失败'
                translate_text += result
            assert translate_text, f'翻译失败 Text:{text}'
            return translate_text
        except AssertionError as e:
            logger.error(e)
            raise ValueError(e)
        except Exception as e:
            logger.error(f'未知错误，错误原因：{e}')
            raise ValueError(f'未知错误，错误原因：{e}')
            # return False

translate = TranslateManager()
if __name__ == '__main__':
    import langcodes
    translate_text = '저작자표시-비영리-동일조건변경허락 2.0 대한민국 이용자는 아래의 조건을 따르는 경우에 한하여 자유롭게 l 이 저작물을 복제, 배포, 전송, 전시, 공연 및 방송할 수 있습니다.l 이차적 저작물을 작성할 수 있습니다.다음과 같은 조건을 따라야 합니다: l 귀하는, 이 저작물의 재이용이나 배포의 경우, 이 저작물에 적용된 이용허락조건 을 명확하게 나타내어야 합니다.l 저작권자로부터 별도의 허가를 받으면 이러한 조건들은 적용되지 않습니다.저작권법에 따른 이용자의'.replace("\n","")
    # # translate_text = '저작자표시-비영리-동일조건변경허락 2.0'
    # Language = translate.get_language(translate_text)
    # Language = langcodes.Language(Language).display_name()
    #
    # result = translate.manager(translate_text,from_lang=Language,to_lang='en')
    # print(result)
    str_ = "manager"
    print(translate.manager(str_,from_lang='en',to_lang='zh'))

